package top.lixunda.ecommerce.server.good.api.entity.dto;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import top.lixunda.common.utils.ObjectValidators;
import top.lixunda.ecommerce.server.business.api.condition.ILambdaQueryWrapperDTO;
import top.lixunda.ecommerce.server.good.api.entity.db.GoodsDO;

import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
 * 后台管理员端查询条件
 * 条件查询商品数据信息，包括分页
 *
 * @author Xumda
 * @version time:2019/12/17 14:01
 */
@ApiModel(value = "后台管理员端查询条件DTO", description = "条件查询商品数据信息，包括分页")
@Slf4j
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
public class GoodsAdminQueryDTO implements ILambdaQueryWrapperDTO<GoodsDO> {

    /**
     * 根据商品名称查询
     */
    @ApiModelProperty(hidden = true)
    @JsonIgnore
    public static final String SEARCH_TYPE_GOODS_NAME = "name";

    /**
     * 根据商品类别查询
     */
    @ApiModelProperty(hidden = true)
    @JsonIgnore
    public static final String SEARCH_TYPE_TYPE = "type";

    /**
     * 默认查询
     */
    @ApiModelProperty(hidden = true)
    @JsonIgnore
    public static final String SEARCH_TYPE_DEFAULT = "default";

    /**
     * 搜索类型，如普通所有，店铺搜索，类别搜索等
     */
    @ApiModelProperty(value = "搜索类型", notes = "如普通所有，店铺搜索，类别搜索等")
    private String searchType;

    /**
     * 搜索字符串
     */
    @ApiModelProperty("搜索字符串")
    private String search;

    /**
     * 商品id，精确查询
     */
    @ApiModelProperty(value = "商品id", notes = "精确查询")
    private Integer id;

    /**
     * 商品分组id，精确查询
     */
    @ApiModelProperty(value = "商品分组id", notes = "精确查询")
    private Integer groupId;

    /**
     * 分组名称, 模糊匹配
     */
    @ApiModelProperty(value = "分组名称", notes = "模糊匹配")
    private String groupName;

    /**
     * 店铺id，精确查询
     */
    @ApiModelProperty(value = "店铺id", notes = "精确查询")
    private Integer storeId;

    /**
     * 店铺名称, 模糊匹配
     */
    @ApiModelProperty(value = "店铺名称", notes = "模糊匹配")
    private String storeName;

    /**
     * 创建人员id，精确查询
     */
    @ApiModelProperty(value = "创建人员id", notes = "精确查询")
    private Integer createUserId;

    /**
     * 创建人员名称, 模糊匹配
     */
    @ApiModelProperty(value = "创建人员名称", notes = "模糊匹配")
    private String createUserName;

    /**
     * 更新人员id
     */
    @ApiModelProperty("更新人员id")
    private Integer updateUserId;

    /**
     * 更新人员名称
     */
    @ApiModelProperty("更新人员名称")
    private String updateUserName;

    /**
     * 删除人员id
     */
    @ApiModelProperty("删除人员id")
    private Integer removeUserId;

    /**
     * 删除人员名称
     */
    @ApiModelProperty("删除人员名称")
    private String removeUserName;

    /**
     * 创建本记录的时间，范围值
     */
    @ApiModelProperty(value = "创建本记录的时间", notes = "范围值")
    private LocalDateTime createTimeBegin;

    /**
     * 更新本记录的时间，范围值
     */
    @ApiModelProperty(value = "更新本记录的时间", notes = "范围值")
    private LocalDateTime updateTimeBegin;

    /**
     * 删除本记录的时间，范围值
     */
    @ApiModelProperty(value = "删除本记录的时间", notes = "范围值")
    private LocalDateTime removeTimeBegin;

    /**
     * 创建本记录的时间，范围值
     */
    @ApiModelProperty(value = "创建本记录的时间", notes = "范围值")
    private LocalDateTime createTimeEnd;

    /**
     * 更新本记录的时间，范围值
     */
    @ApiModelProperty(value = "更新本记录的时间", notes = "范围值")
    private LocalDateTime updateTimeEnd;

    /**
     * 删除本记录的时间，范围值
     */
    @ApiModelProperty(value = "删除本记录的时间", notes = "范围值")
    private LocalDateTime removeTimeEnd;

    /**
     * 商品名称，模糊匹配
     */
    @ApiModelProperty(value = "商品名称", notes = "模糊匹配")
    private String name;

    /**
     * 分类id，系统分类
     */
    @ApiModelProperty(value = "分类id", notes = "系统分类")
    private Integer goodCategoryId;

    /**
     * 分类名称，系统分类
     */
    @ApiModelProperty(value = "分类名称", notes = "系统分类")
    private String goodCategoryName;

    /**
     * 卖点
     */
    @ApiModelProperty(value = "卖点")
    private String sellPoint;

    /**
     * 热度得分，范围值
     */
    @ApiModelProperty(value = "卖点")
    private BigDecimal scoreBegin;

    /**
     * 热度得分，范围值
     */
    @ApiModelProperty(value = "热度得分", notes = "范围值")
    private BigDecimal scoreEnd;

    /**
     * 运费，为0时表示包邮，范围值
     */
    @ApiModelProperty(value = "运费", notes = "范围值，为0时表示包邮")
    private BigDecimal freightBegin;

    /**
     * 运费，为0时表示包邮，范围值
     */
    @ApiModelProperty(value = "运费", notes = "范围值，为0时表示包邮")
    private BigDecimal freightEnd;

    /**
     * 上架时间，范围值
     */
    @ApiModelProperty(value = "上架时间", notes = "范围值")
    private LocalDateTime pushTimeBegin;

    /**
     * 上架时间，范围值
     */
    @ApiModelProperty(value = "上架时间", notes = "范围值")
    private LocalDateTime pushTimeEnd;

    /**
     * 下架时间，范围值
     */
    @ApiModelProperty(value = "下架时间", notes = "范围值")
    private LocalDateTime pullTimeBegin;

    /**
     * 下架时间，范围值
     */
    @ApiModelProperty(value = "下架时间", notes = "范围值")
    private LocalDateTime pullTimeEnd;

    /**
     * 商品状态：待审核，审核中，审核失败，未上架，售卖中（正常），缺货中...
     */
    private String state;

    /**
     * 状态描述，可以是审核失败原因，模糊匹配
     */
    @ApiModelProperty(value = "状态描述", notes = "可以是审核失败原因，模糊匹配")
    private String stateDesc;

    /**
     * 审核人员
     */
    @ApiModelProperty(value = "审核人员")
    private Integer checkUserId;

    /**
     * 审核人员名称
     */
    @ApiModelProperty(value = "审核人员名称")
    private String checkUserName;

    /**
     * 审核时间，范围值
     */
    @ApiModelProperty(value = "审核时间", notes = "范围值")
    private LocalDateTime checkTimeBegin;

    /**
     * 审核时间，范围值
     */
    @ApiModelProperty(value = "审核时间", notes = "范围值")
    private LocalDateTime checkTimeEnd;

    /**
     * 处理搜索条件
     *
     * @param wrapper 条件构造器
     */
    private void dealWithSearchWrapper(LambdaQueryWrapper<GoodsDO> wrapper) {
        if (ObjectValidators.isNotEmpty(this.search) && ObjectValidators.isNotEmpty(this.searchType)) {
            switch (searchType) {
                // default
                case GoodsAdminQueryDTO.SEARCH_TYPE_DEFAULT:
                    break;
                // name
                case GoodsAdminQueryDTO.SEARCH_TYPE_GOODS_NAME:
                    break;
                // type
                case GoodsAdminQueryDTO.SEARCH_TYPE_TYPE:
                    break;
                default:
                    log.debug("不存在的搜索方式 {}", this.searchType);
            }
        }
    }

    /**
     * 处理创建时间
     *
     * @param wrapper 条件构造器
     */
    private void dealWithCreateTime(LambdaQueryWrapper<GoodsDO> wrapper) {
        if (ObjectValidators.isNotEmpty(createTimeBegin)) {
            wrapper.ge(GoodsDO::getCreateTime, createTimeBegin);
        }
        if (ObjectValidators.isNotEmpty(createTimeEnd)) {
            wrapper.le(GoodsDO::getCreateTime, createTimeEnd);
        }
    }

    /**
     * 处理更新时间
     *
     * @param wrapper 条件构造器
     */
    private void dealWithUpdateTime(LambdaQueryWrapper<GoodsDO> wrapper) {
        if (ObjectValidators.isNotEmpty(updateTimeBegin)) {
            wrapper.ge(GoodsDO::getUpdateTime, updateTimeBegin);
        }
        if (ObjectValidators.isNotEmpty(updateTimeEnd)) {
            wrapper.le(GoodsDO::getUpdateTime, updateTimeEnd);
        }
    }

    /**
     * 处理移除时间
     *
     * @param wrapper 条件构造器
     */
    private void dealWithRemoveTime(LambdaQueryWrapper<GoodsDO> wrapper) {
        if (ObjectValidators.isNotEmpty(removeTimeBegin)) {
            wrapper.ge(GoodsDO::getRemoveTime, removeTimeBegin);
        }
        if (ObjectValidators.isNotEmpty(removeTimeEnd)) {
            wrapper.le(GoodsDO::getRemoveTime, removeTimeEnd);
        }
    }

    private void dealWithScore(LambdaQueryWrapper<GoodsDO> wrapper) {
        if (ObjectValidators.isNotEmpty(scoreBegin)) {
            wrapper.ge(GoodsDO::getScore, scoreBegin);
        }
        if (ObjectValidators.isNotEmpty(scoreEnd)) {
            wrapper.le(GoodsDO::getScore, scoreEnd);
        }
    }

    private void dealWithFreight(LambdaQueryWrapper<GoodsDO> wrapper) {
        if (ObjectValidators.isNotEmpty(freightBegin)) {
            wrapper.ge(GoodsDO::getFreight, freightBegin);
        }
        if (ObjectValidators.isNotEmpty(freightEnd)) {
            wrapper.le(GoodsDO::getFreight, freightEnd);
        }
    }

    private void dealWithPushTime(LambdaQueryWrapper<GoodsDO> wrapper) {
        if (ObjectValidators.isNotEmpty(pushTimeBegin)) {
            wrapper.ge(GoodsDO::getPushTime, pushTimeBegin);
        }
        if (ObjectValidators.isNotEmpty(pushTimeEnd)) {
            wrapper.le(GoodsDO::getPushTime, pushTimeEnd);
        }
    }

    private void dealWithCheckTime(LambdaQueryWrapper<GoodsDO> wrapper) {
        if (ObjectValidators.isNotEmpty(checkTimeBegin)) {
            wrapper.ge(GoodsDO::getCheckTime, checkTimeBegin);
        }
        if (ObjectValidators.isNotEmpty(checkTimeEnd)) {
            wrapper.le(GoodsDO::getCheckTime, checkTimeEnd);
        }
    }

    private void dealWithPullTime(LambdaQueryWrapper<GoodsDO> wrapper) {
        if (ObjectValidators.isNotEmpty(pullTimeBegin)) {
            wrapper.ge(GoodsDO::getPullTime, pullTimeBegin);
        }
        if (ObjectValidators.isNotEmpty(pullTimeEnd)) {
            wrapper.le(GoodsDO::getPullTime, pullTimeEnd);
        }
    }

    /**
     * 将当前用于查询的DTO中的查询数据转换为 LambdaQuerySqlWrapper
     *
     * @return 条件构造器 LambdaQuerySqlWrapper
     */
    @SuppressWarnings("Duplicates")
    @Override
    public LambdaQueryWrapper<GoodsDO> toWrapper() {
        LambdaQueryWrapper<GoodsDO> wrapper = new LambdaQueryWrapper<>();
        if (ObjectValidators.isNotEmpty(id) && id > 0) {
            wrapper.eq(GoodsDO::getId, id);
        }
        if (ObjectValidators.isNotEmpty(groupId) && groupId > 0) {
            wrapper.eq(GoodsDO::getGroupId, groupId);
        }
        if (ObjectValidators.isNotEmpty(groupName)) {
            wrapper.like(GoodsDO::getGroupName, groupName);
        }
        if (ObjectValidators.isNotEmpty(storeId) && storeId > 0) {
            wrapper.eq(GoodsDO::getStoreId, storeId);
        }
        if (ObjectValidators.isNotEmpty(storeName)) {
            wrapper.like(GoodsDO::getStoreName, storeName);
        }
        if (ObjectValidators.isNotEmpty(createUserId) && createUserId > 0) {
            wrapper.eq(GoodsDO::getCreateUserId, createUserId);
        }
        if (ObjectValidators.isNotEmpty(createUserName)) {
            wrapper.like(GoodsDO::getCreateUserName, createUserName);
        }
        if (ObjectValidators.isNotEmpty(updateUserId) && updateUserId > 0) {
            wrapper.eq(GoodsDO::getUpdateUserId, updateUserId);
        }
        if (ObjectValidators.isNotEmpty(updateUserName)) {
            wrapper.like(GoodsDO::getUpdateUserName, updateUserName);
        }
        if (ObjectValidators.isNotEmpty(removeUserId) && removeUserId > 0) {
            wrapper.eq(GoodsDO::getRemoveUserId, removeUserId);
        }
        if (ObjectValidators.isNotEmpty(removeUserName)) {
            wrapper.like(GoodsDO::getRemoveUserName, removeUserName);
        }
        dealWithCreateTime(wrapper);
        dealWithUpdateTime(wrapper);
        dealWithRemoveTime(wrapper);
        dealWithSearchWrapper(wrapper);
        if (ObjectValidators.isNotEmpty(name)) {
            wrapper.like(GoodsDO::getName, name);
        }
        if (ObjectValidators.isNotEmpty(goodCategoryId) && goodCategoryId > 0) {
            wrapper.eq(GoodsDO::getGoodCategoryId, goodCategoryId);
        }
        if (ObjectValidators.isNotEmpty(goodCategoryName)) {
            wrapper.like(GoodsDO::getGoodCategoryName, goodCategoryName);
        }
        if (ObjectValidators.isNotEmpty(sellPoint)) {
            wrapper.like(GoodsDO::getSellPoint, sellPoint);
        }
        dealWithScore(wrapper);
        dealWithFreight(wrapper);
        dealWithPushTime(wrapper);
        dealWithPullTime(wrapper);
        if (ObjectValidators.isNotEmpty(state)) {
            wrapper.eq(GoodsDO::getState, state);
        }
        if (ObjectValidators.isNotEmpty(stateDesc)) {
            wrapper.like(GoodsDO::getStateDesc, stateDesc);
        }
        if (ObjectValidators.isNotEmpty(checkUserId) && checkUserId > 0) {
            wrapper.eq(GoodsDO::getCheckUserId, checkUserId);
        }
        if (ObjectValidators.isNotEmpty(checkUserName)) {
            wrapper.like(GoodsDO::getCheckUserName, checkUserName);
        }
        dealWithCheckTime(wrapper);
        return wrapper;
    }
}
